#include "viewwindow.h"
#include "viewer.h"
#include <osgViewer/ViewerEventHandlers>
#include "manipulatormanager.h"
#include "mimedata.h"
//#include <QVBoxLayout>

#define DEFAULT_INTERVAL 30

namespace PublicGui
{
	AdapterWidget::AdapterWidget(const QGLFormat& format,QWidget* parent,Qt::WindowFlags f,const QGLWidget* shareWidget,bool forwardKeyEvents)
		:osgQt::GLWidget(format,parent,shareWidget,f,forwardKeyEvents),_manipulatorManager(NULL),_breakToolTip(true)
	{
		setFocusPolicy(Qt::StrongFocus);
		//for get Qt' mousemove message!
		setMouseTracking( true );
		setAcceptDrops(true);
		_isActiveView = true ;
		setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
		//GetCompositeViewer()->getView(0)->getCamera()->setSmallFeatureCullingPixelSize(SMALLFEATURECULLINGPIXELSIZE);
	}

	osgViewer::GraphicsWindow* AdapterWidget::getGraphicsWindow()
	{
		return dynamic_cast<osgViewer::GraphicsWindow*>(_viewer->getCamera()->getGraphicsContext());
	}

	void AdapterWidget::enableActiveView( bool enable )
	{
		_isActiveView = enable ;
	}

	//QWidget* AdapterWidget::getGLWidget()
	//{
	//	QWidget* glw = dynamic_cast<osgQt::GraphicsWindowQt*>(getGraphicsWindow())->getGLWidget();
	//	glw->setFocusPolicy(Qt::StrongFocus);
	//	//for get Qt' mousemove message!
	//	glw->setMouseTracking( true );
	//	return glw;
	//}

	void AdapterWidget::initializeGL()
	{
		/*osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->windowName = "mainWindow";
        traits->windowDecoration = false;
        traits->x = 0;
        traits->y = 0;
        traits->width = width();
        traits->height = height();
        traits->doubleBuffer = true;
        traits->alpha = ds->getMinimumNumAlphaBits();
        traits->stencil = ds->getMinimumNumStencilBits();
        traits->sampleBuffers = ds->getMultiSamples();
        traits->samples = ds->getNumMultiSamples();*/
		_viewer = new CoreBase::Viewer();
		osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setGraphicsContext( new osgQt::GraphicsWindowQt(dynamic_cast<osgQt::GLWidget*>(this)));
        camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
		camera->setViewport( 0, 0, width(), height() ) ;
		camera->setProjectionMatrixAsPerspective(45.0f,static_cast<double>(width())/static_cast<double>(height()), 2.0f, 3000.0f);
		//_viewer->getCamera()->setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);
		_viewer->setCamera(camera);
		addView(_viewer);
		QObject::connect(&_timer, SIGNAL(timeout()),this, SLOT(updateGL()));
		_timer.start(DEFAULT_INTERVAL);
	}

	void AdapterWidget::resizeEvent(QResizeEvent* event)
	{
		int width = event->size().width();
		int height = event->size().height();
		getGraphicsWindow()->getEventQueue()->windowResize(0, 0, width, height );
		getGraphicsWindow()->resized(0,0,width,height);

		_viewer->getCamera()->setViewport( 0, 0, width, height ) ;
		restoreSurface() ;
	}

	void AdapterWidget::glDraw()
	{
		if( !_viewer->done() && _isActiveView )
			frame();
	}

	void AdapterWidget::testViewChange()
	{
		if(_viewerVector.size()!=_views.size())
		{
			_viewerVector.clear();
			for(int i=0;i<_views.size();++i)
			{
				_viewerVector.push_back(static_cast<CoreBase::Viewer*>(_views.at(i).get()));
			}
		}
	}

	void AdapterWidget::frame(double simulationTime)
	{
		if (_done) return;
		if (_firstFrame)
		{
			viewerInit();
			if (!isRealized())
			{
				realize();
			}
			_firstFrame = false;
		}
		advance(simulationTime);
		eventTraversal();
		testViewChange();
		for(int i=0;i<_viewerVector.size();++i)
		{
			if(_viewerVector.at(i)->isSetupScene())
			{
				_viewerVector.at(i)->getScene()->postEventTraversal(simulationTime);
				_viewerVector.at(i)->getScene()->prePhysicsStepUpdate(simulationTime);
			}
		}
		updateTraversal();
		renderingTraversals();
		for(int i=0;i<_viewerVector.size();++i)
		{
			if(_viewerVector.at(i)->isSetupScene())
			{
				_viewerVector.at(i)->getScene()->frameStepUpdate(simulationTime);
				_viewerVector.at(i)->getScene()->postPhysicsStepUpdate(simulationTime);
			}
		}
	}

	AdapterWidget::~AdapterWidget()
	{
		_timer.stop();
		if(_manipulatorManager!=NULL)
		{
			delete _manipulatorManager;
			_manipulatorManager = NULL;
		}
	}

	ControlCenter::ManipulatorManager* AdapterWidget::getManipulatorManager()
	{
		return _manipulatorManager;
	}

	SceneViewer::SceneViewer(const QGLFormat& format,int viewtype,QWidget* parent,Qt::WindowFlags f):
	AdapterWidget(format,parent,f),_viewType(viewtype)
	{
		initializeGL();
	}

	SceneViewer::~SceneViewer()
	{}

	void SceneViewer::initializeGL()
	{
		if(_viewer.valid())
			return;
		AdapterWidget::initializeGL();
		setClearColor(0.5, 0.5, 0.5, 1.0 ) ;			//set clear color
		setPolygonMode(0) ;								//set polygon mode
		#ifndef NDEBUG
		{
			_viewer->addEventHandler(new osgViewer::StatsHandler);
		}
		#else
		{
			_viewer->setStats(NULL);
		}
		#endif
		CoreBase::Scene* mainscene = new CoreBase::Scene;
		setScene(mainscene);
		_manipulatorManager = new ControlCenter::ManipulatorManager(dynamic_cast<CoreBase::Viewer*>(_viewer.get()),
			mainscene,_viewType);
		//QVBoxLayout* mvLayout=new QVBoxLayout(this);
		////mvLayout->setSpacing(0);
		//mvLayout->setMargin(0);
		//mvLayout->addWidget(getGLWidget());
	}

	void SceneViewer::setManipulator(osgGA::CameraManipulator* mani)
	{
		if( !mani)
			return ;
		//setCameraManipulator(mani) ;
		//m_camerahandler->setCameraManipulator(mani);
		//osgGA::MatrixManipulator * test = new osgGA::TerrainManipulator ;
		//setCameraManipulator(test) ;

		//test collision
		//((HTSDMaxManipulator*)mani)->setView( this ) ;
	}

	void SceneViewer::setClearColor( float r, float g, float b, float a ) 
	{
		osg::Vec4 cc(r,g,b,a) ;
		_viewer->getCamera()->setClearColor(cc) ;
		_viewer->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
	}

	void SceneViewer::setClearImage(const std::string& imagename )
	{
		//if( _bgcamera.valid() )
		//	_bgcamera->addChild( HTSDComShapeNodes::createBackGroundRect( imagename )) ;
		////close color-clear
		//if( !imagename.empty() )
		//	getCamera()->setClearMask( GL_DEPTH_BUFFER_BIT );
		//else
		//	getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}

	void SceneViewer::setPolygonMode(int mode,int face)
	{
		//int pmode, pface ;
		//if( mode == 1 )
		//	pmode = osg::PolygonMode::LINE ;
		//else
		//	pmode = osg::PolygonMode::FILL ;
		//pface = osg::PolygonMode::FRONT ;
		//if( pface == 1 )
		//	pface = osg::PolygonMode::BACK ;
		//else if( pface == 2 )
		//	pface = osg::PolygonMode::FRONT_AND_BACK ;
		//else
		//	return ;
		//osg::StateSet *ss = getCamera()->getStateSet();//getOrCreateStateSet();//getStateSet() ;
		//osg::PolygonMode *pm = new osg::PolygonMode( (osg::PolygonMode::Face)pface,
		//	(osg::PolygonMode::Mode)pmode ) ;
		//ss->setAttribute( pm ) ;
	}

	void SceneViewer::setCullFace(int mode,bool enable)
	{
		//int pmode = osg::CullFace::FRONT ;
		//if( mode == 1 )
		//	pmode = osg::CullFace::BACK ;
		//else if( mode == 2 )
		//	pmode = osg::CullFace::FRONT_AND_BACK ;
		//else
		//	return ;
		//osg::CullFace *cf = new osg::CullFace( (osg::CullFace::Mode)pmode ) ;
		//osg::StateSet *ss = getCamera()->getStateSet() ;
		//if( enable )
		//	ss->setAttributeAndModes( cf, osg::StateAttribute::ON );
		//else
		//	ss->setAttributeAndModes( cf, osg::StateAttribute::OFF );
	}

	//void SceneViewer::createBgCamera() 
	//{
		//_bgcamera = new osg::Camera ;
		//_bgcamera->setRenderOrder(osg::Camera::PRE_RENDER) ;
		//_bgcamera->setProjectionMatrix(osg::Matrix::ortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0));
		//_bgcamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
		//_bgcamera->setViewMatrix(osg::Matrix::identity());
		//_bgcamera->setAllowEventFocus(false);
	//}

	void SceneViewer::setScene(CoreBase::Scene* scene,CoreBase::Viewer* viewer) 
	{
		if(scene) 
		{
			if(viewer!=NULL)
				viewer->setScene(scene);
			else
				dynamic_cast<CoreBase::Viewer*>(_viewer.get())->setScene(scene);
		}
	}

	CoreBase::Scene* SceneViewer::getScene(CoreBase::Viewer* viewer) const 
	{
		if(viewer == NULL)
			return dynamic_cast<CoreBase::Viewer*>(_viewer.get())->getScene();
		else
			return viewer->getScene();
	}

	void SceneViewer::addIntoScene(CoreBase::Drawable *drawable,CoreBase::Viewer* viewer) 
	{
		CoreBase::Scene* scene = viewer==NULL?dynamic_cast<CoreBase::Viewer*>(_viewer.get())->getScene():viewer->getScene();
		if(drawable)
		{
			scene->addDrawable(drawable) ;
		}
	}

	void SceneViewer::delFrmScene( CoreBase::Drawable* drawable,CoreBase::Viewer* viewer) 
	{
		CoreBase::Scene* scene = viewer==NULL?dynamic_cast<CoreBase::Viewer*>(_viewer.get())->getScene():viewer->getScene();
		if(drawable)
		{
			scene->removeDrawable( drawable ) ;
		}
	}
}